'''

一款多线程下载文件的python程序，

XunLei和XunLeiQueue,道理差不多，后者是用Queue写的并发，前者是用列表实现queue，
按理论后者更优势一些。

本程序没有处理线程坏死和任务重启续传，有很大的改善空间

用法就

x = XunLei(url)        #实例化：输入一个下载文件的链接
#x = XunLeiQueue(url)
x.my_thread(开启的线程数量 )  #调用my_thread 函数 传入一个要开启的线程数量


'''
import requests
import glob
import queue
import threading
from collections import deque


class XunLei:

    
    headers = {
    
    'Accept-Encoding': 'identity;q=1, *;q=0',
    'Range': 'bytes=0-',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',

          }
    def __init__(self,
                 url,
                 ):
        self.num = 0

        self.url = url
        self.content_length = self.get_content_length()
        print('该文件长度为：{} b'.format(self.content_length))

        print(dir())
        


    def get_content_length(self):
        print('************')

        r = requests.head(self.url,headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'})
        print(r)
        content_length = int(r.headers['Content-Length'])
        
        return content_length


    def take_queue(self):

        '''
        '''
        
        xlist = []

        queue_len = self.content_length//100000+1
   
        for i in range(queue_len):

            if i == 0:

                xlist.append('bytes={}-{}'.format(0,100000))

            elif i != queue_len-1:

                xlist.append('bytes={}-{}'.format(i*100000+1,(i+1)*100000))

            elif i == queue_len-1:

                xlist.append('bytes={}-{}'.format(i*100000+1,''))

        self.queue_list = deque(list(enumerate(xlist)))
        
        self.num = 1

        



    

    def save_file(self):

        xlocal.acquire()

        if self.num == 0:

            self.take_queue()
        xlocal.release()

        while True:
            
            info = self.queue_list.popleft()
            print(info)

            headers = {
        
                'Accept-Encoding': 'identity;q=1, *;q=0',
                'Range': info[1],
                #'Referer': 'http://audio.xmcdn.com/group46/M0B/5D/33/wKgKj1t4VZixygwxAJtZ5lvCEBE822.m4a',
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',

                      }

            r = requests.get(self.url,headers = headers)

            with open('{}.xl'.format(info[0]),'wb') as f:

                f.write(r.content)

    def my_thread(self,thread_num):

        xlocal = threaing.Local()

        pool = []
        for i in range(thread_num):     
            pool.append(threading.Thread(target = self.save_file))
        for i in pool:
            i.start()
        for i in pool:
            i.join()

        x = glob.glob('*.xl')
        x.sort(key = lambda x:int(x[:-3]))

        file = open('xx.mp3','ab')

        for i in x:
            with open(i,'rb') as f:

                file.write(f.read())


class XunLeiQueue(XunLei):

    def __init__(self,url):
        super().__init__(url)
        self.url = url
        self.q = queue.Queue(5)

    def make_queue(self):

        queue_len = self.content_length//100000+1
   
        for i in range(queue_len):#2

            if i == 0:

                self.q.put((i,'bytes={}-{}'.format(0,100000)))

            elif i != queue_len-1:

                self.q.put((i,'bytes={}-{}'.format(i*100000+1,(i+1)*100000)))

            elif i == queue_len-1:

                self.q.put((i,'bytes={}-{}'.format(i*100000+1,'')))

    def save_file(self):

        while True:

            info = self.q.get()
            
            if info == None:
                break

            print(info)
            
            

            headers = {
        
                'Accept-Encoding': 'identity;q=1, *;q=0',
                'Range': info[1],     
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',

                      }

            r = requests.get(self.url,headers = headers)

            with open('{}.xl'.format(info[0]),'wb') as f:

                f.write(r.content)

            self.q.task_done()

    def my_thread(self,thread_num):
        
        thread_pool = []
        for i in range(thread_num):

            t = threading.Thread(target = self.save_file)
            t.start()

            thread_pool.append(t)

        self.make_queue()

        self.q.join()

        for i in range(thread_num):

            self.q.put(None)

        for t in thread_pool:
            t.join()

        x = glob.glob('*.xl')
        x.sort(key = lambda x:int(x[:-3]))

        file = open('xx.mp3','ab')

        for i in x:
            with open(i,'rb') as f:

                file.write(f.read())

        

        
            
        
        
        


if __name__ == '__main__':

    url = 'http://mting.info/asdb/other/xxsbbgs80/9v9y5dqj.mp3'

    x = XunLei(url).save_file()


    

   

        

                             

                

            

                        

            

            


        

        

    







































